package com.iussoft.gateway.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.apache.tools.StrUtil;
import com.iussoft.gateway.filter.Response;
import com.iussoft.gateway.routes.GatewayDefineService;
import com.iussoft.gateway.routes.GatewayServiceHandler;
import com.iussoft.tools.AddressUtils;
import com.iussoft.tools.HttpService;
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.DiscoveryManager;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description: 添加路由配置
 * @author: Hou Dayu
 * @date: Created in 2020/2/24
 */
@RestController
public class RouteController {

    @Autowired
    private GatewayServiceHandler gatewayServiceHandler;

    @Autowired
    private GatewayDefineService gatewayDefineService;

    /**
     * 刷新路由配置
     */
    @GetMapping("/route/refresh")
    public String refresh(ServerHttpRequest request) throws Exception {
        String infoId = request.getQueryParams().getFirst("cacheKey");
        if(StrUtil.isNotNull(infoId)){//刷新指定路由
            Map<String,String> param = new HashMap<>(1);
            param.put("infoId",infoId);
            gatewayServiceHandler.update(param);
            return "success";
        } else {
            return this.gatewayServiceHandler.loadRouteConfig();
        }
    }

    /**
     * 刷新黑白名单配置
     */
    @GetMapping("/route/refreshWhite")
    public String refreshWhite(ServerHttpRequest request) throws Exception {
        String ip = request.getQueryParams().getFirst("cacheKey");
        this.gatewayServiceHandler.loadWhiteList(ip);
        return "success";
    }

    /**
     * 增加路由记录
     */
   @PostMapping("/route/add")
    public String add(ServerHttpRequest request, @RequestBody Map<String,String> param) throws Exception {
        gatewayDefineService.saveGatewayDefine(param);
        gatewayServiceHandler.saveRoute(param);
        return "success";
    }

    @PostMapping("/route/update")
    public String update(ServerHttpRequest request, @RequestBody Map<String,String> param) throws Exception {
        gatewayDefineService.updateGatewayDefine(param);
        gatewayServiceHandler.update(param);
        return "success";
    }

    @GetMapping("/route/delete")
    public String delete(ServerHttpRequest request) throws Exception {
       String id = request.getQueryParams().getFirst("cacheKey");
       gatewayDefineService.deleteGatewayDefine(id);
       gatewayServiceHandler.deleteRoute(id);
       return "success";
    }

    /**
     * 下线本项目
     */
    @RequestMapping(value = "/offline", method = RequestMethod.GET)
    @ResponseBody
    public String offLine(ServerHttpRequest request) {
        String sign = request.getQueryParams().getFirst("sign");
        if("Constant.OFFLINE_KEY".equals(sign)){
            //EurekaClientConfig ecc = DiscoveryManager.getInstance().getEurekaClientConfig();
            //EurekaInstanceConfig eic = DiscoveryManager.getInstance().getEurekaInstanceConfig();
            //ApplicationInfoManager.getInstance().setInstanceStatus(InstanceInfo.InstanceStatus.DOWN);
            //DiscoveryManager.getInstance().initComponent(eic, ecc);
            DiscoveryManager.getInstance().shutdownComponent();
            return "下线成功";
        }
        return "签名不正确";
    }

    /**
     * 项目手动上线
     */
    @RequestMapping(value = "/online", method = RequestMethod.GET)
    @ResponseBody
    public String online(){
        if(!InstanceInfo.InstanceStatus.UP.equals(ApplicationInfoManager.getInstance().getInfo().getStatus())) {
            EurekaClientConfig ecc = DiscoveryManager.getInstance().getEurekaClientConfig();
            EurekaInstanceConfig eic = DiscoveryManager.getInstance().getEurekaInstanceConfig();
            ApplicationInfoManager.getInstance().setInstanceStatus(InstanceInfo.InstanceStatus.UP);
            DiscoveryManager.getInstance().initComponent(eic, ecc);
            return "上线成功";
        } else {
            return "服务处于发布状态不需上线操作";
        }
    }

    @GetMapping("/fallback")
    public Response fallback() {
        Response response = new Response();
        response.setErrorCode("100");
        response.setErrorMessage("服务暂时不可用");
        return response;
    }

    /**
     * 注册中心服务列表
     * @return
     */
    @RequestMapping(value = "/serverList", method = RequestMethod.GET)
    @ResponseBody
    public Object eurekaServers(){
        Map<String,Object> data = new HashMap<>();

        DiscoveryManager discoveryClient = DiscoveryManager.getInstance();
        if (null == discoveryClient.getEurekaClient()) {
            data.put("flag", "F");
            data.put("msg", "没有找到注册服务信息");
            return data;
        }
        data.put("flag", "T");
        Applications apps = discoveryClient.getEurekaClient().getApplications();
        List listInfo = new ArrayList();
        for(Application app : apps.getRegisteredApplications()){
            Map<String,Object> appMap = new HashMap<>();
            appMap.put("serverName",app.getName());
            List<InstanceInfo> list = app.getInstances();
            appMap.put("serverNum",list.size());
            int up = 0;
            int down = 0;
            List details = new ArrayList();
            for(InstanceInfo info:list){
                Map<String,Object> infoMap = new HashMap<>();
                String homeUrl = info.getHomePageUrl();
                String str = HttpService.sendGetHttp(info.getHomePageUrl()+"info",null);
                infoMap.put("contextPath","");
                if(StrUtil.isNotNull(str)){
                    com.alibaba.fastjson.JSONObject json = JSON.parseObject(str);
                    if(json.getJSONObject("app").containsKey("context-path")) {
                        infoMap.put("contextPath", json.getJSONObject("app").getString("context-path"));
                    }
                }
                String address = info.getIPAddr();
                homeUrl = homeUrl.replaceAll(info.getHostName(),address);
                if(info.getStatus().toString().equalsIgnoreCase("UP")){
                    up++;
                    infoMap.put("statusPageUrl",info.getHomePageUrl()+"info");
                    infoMap.put("homePageUrl",info.getHomePageUrl().replaceAll(info.getHostName(),address));
                    details.add(infoMap);
                    appMap.put("up",details);
                }else{
                    down++;
                    infoMap.put("statusPageUrl",homeUrl);
                    infoMap.put("homePageUrl",info.getHomePageUrl().replaceAll(info.getHostName(),address));
                    details.add(infoMap);
                    appMap.put("down",details);
                }
            }
            appMap.put("statusUp",up);
            appMap.put("statusDown",down);
            listInfo.add(appMap);
        }
        data.put("total",listInfo.size());
        data.put("rows",listInfo);
        return data;
    }
}
